<template>
  <div class="chat-container manus-app">
    <div class="chat-header">
      <div style="display:flex;justify-content:space-between;align-items:center">
        <div>AI 超级智能体</div>
        <div>聊天室 ID: {{ chatId }}</div>
      </div>
    </div>

    <div class="chat-body" ref="bodyRef">
      <div v-if="messages.length===0" class="system-note">开始新的对话，输入你的话...</div>
      <div v-for="(m, idx) in messages" :key="idx" :class="['message-row', m.role==='user' ? 'user-row' : 'ai-row']">
        <template v-if="m.role==='ai'">
          <div class="avatar ai">A</div>
          <div class="message-bubble" v-html="m.content"></div>
        </template>
        <template v-else>
          <div class="message-bubble" v-html="m.content"></div>
          <div class="avatar user">你</div>
        </template>
      </div>
    </div>

    <div class="chat-input">
      <input v-model="input" @keydown.enter.prevent="sendMessage" class="input" placeholder="输入消息，回车发送" />
      <button class="btn" @click="clear">清空</button>
      <button class="btn primary" @click="sendMessage">发送</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'

const messages = ref<{role:string, content:string}[]>([])
const input = ref('')
const chatId = ref('')
const esRef = ref<EventSource | null>(null)
const bodyRef = ref<HTMLElement | null>(null)

function genChatId(){
  return 'chat-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2,8)
}

function scrollToBottom(){
  nextTick(()=>{
    if(bodyRef.value){
      bodyRef.value.scrollTop = bodyRef.value.scrollHeight
    }
  })
}

function createEventSource(url: string, onChunk: (chunk: string)=>void){
  // create and return an EventSource that calls onChunk for each incoming message
  try{
    const es = new EventSource(url)
    es.onmessage = (e) => {
      const data = e.data
      if(data) onChunk(data)
    }
    es.onerror = (err) => {
      // close on error
      try{ es.close() }catch(_){}
    }
    return es
  }catch(e){
    return null
  }
}

async function sendMessage(){
  const text = input.value && input.value.trim()
  if(!text) return
  messages.value.push({role:'user', content: text})
  input.value = ''
  scrollToBottom()

  const url = 'http://localhost:8123/api/ai/manus/chat?message=' + encodeURIComponent(text)

  // close previous
  if(esRef.value){ try{ esRef.value.close() }catch(_){}; esRef.value = null }

  // First try EventSource which matches SseEmitter better
  const es = createEventSource(url, (chunk)=>{
    // Each incoming event is treated as one step -> create a new AI message bubble
    console.debug('[ManusApp] chunk received (ES):', chunk)
    messages.value.push({ role: 'ai', content: chunk })
    scrollToBottom()
  })

  if(es){
    esRef.value = es
    return
  }

  // Fallback: fetch + ReadableStream — accumulate buffer and split into steps
  try{
    const r = await fetch(url)
    if(!r.body) throw new Error('no body')
    const reader = r.body.getReader()
    const decoder = new TextDecoder()
    let done = false
    let buffer = ''
    const flushBuffer = (force=false) => {
      // try double-newline then single newline as separators
      let delim = '\n\n'
      if(buffer.includes(delim)){
        const parts = buffer.split(delim)
        for(let i=0;i<parts.length-1;i++){
          const part = parts[i].trim()
          if(part) messages.value.push({role:'ai', content: part})
        }
        buffer = parts[parts.length-1]
      } else if(buffer.includes('\n')){
        const parts = buffer.split('\n')
        for(let i=0;i<parts.length-1;i++){
          const part = parts[i].trim()
          if(part) messages.value.push({role:'ai', content: part})
        }
        buffer = parts[parts.length-1]
      } else if(force && buffer.trim()){
        messages.value.push({role:'ai', content: buffer.trim()})
        buffer = ''
      }
      if(messages.value.length) scrollToBottom()
    }

    while(!done){
      const {value, done: d} = await reader.read()
      done = d
      if(value){
        const chunk = decoder.decode(value, {stream: true})
        console.debug('[ManusApp] chunk received (fetch):', chunk)
        buffer += chunk
        flushBuffer(false)
      }
    }

    // flush any remainder as the last step
    flushBuffer(true)
  }catch(err){
    console.error('[ManusApp] fetch stream error', err)
    messages.value.push({role:'ai', content: '\n[错误] 无法建立流连接'})
  }
}

function clear(){
  messages.value = []
  chatId.value = ''
}

onMounted(()=>{
  chatId.value = genChatId()
})

onBeforeUnmount(()=>{
  // nothing special
})
</script>

<style scoped>
.message { white-space:pre-wrap }
</style>
